package de.koller.oceanFramework.plain;

import de.koller.oceanFramework.tree.Sea3X;
import java.awt.Canvas;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 
 * @author Fabian Koller
 */
public class Input extends Sea3X {
	
	private PlainOceanGame game;
	
	private Set<Key> keyPressed = new TreeSet<>();
	private Set<Key> keyTyped = new TreeSet<>();
	
	private Set<Button> buttonPressed = new TreeSet<>();
	private Set<Button> buttonTyped = new TreeSet<>();
	
	private List<Character> charPressed = new ArrayList<>();
	
	private int mouseX;
	private int mouseY;
	
	Input( PlainOceanGame game ) {
		this( (Canvas)game );
		this.game = game;
	}

	public Input( Canvas canvas ) {
		canvas.addKeyListener( new InputReceiver() );
		
		MouseInputReceiver mir = new MouseInputReceiver();
		canvas.addMouseListener( mir );
		canvas.addMouseMotionListener( mir );
	}
	
	/**
	 * 
	 * @param elapsedTime
	 */
	@Override
	public void postChildUpdate( int elapsedTime ) {
		super.postChildUpdate( elapsedTime );
		
		keyTyped.clear();
		buttonTyped.clear();
		charPressed.clear();
	}
	
	/**
	 * 
	 * @param key
	 * @return
	 */
	public boolean isKeyDown( Key key ) {
		return keyPressed.contains( key );
	}
	
	/**
	 * 
	 * @param key
	 * @return
	 */
	public boolean isKeyPressed( Key key ) {
		return keyTyped.contains( key );
	}
	
	/**
	 * 
	 * @param button
	 * @return
	 */
	public boolean isMouseDown( Button button ) {
		return buttonPressed.contains( button );
	}
	
	/**
	 * 
	 * @param button
	 * @return
	 */
	public boolean isMousePressed( Button button ) {
		return buttonTyped.contains( button );
	}

	/**
	 * 
	 * @return
	 */
	public int getMouseX() {
		return mouseX;
	}

	/**
	 * 
	 * @return
	 */
	public int getMouseY() {
		return mouseY;
	}

	public List<Character> getCharPressed() {
		return charPressed;
	}
	
	private class MouseInputReceiver extends MouseAdapter {
		
		@Override
		public void mouseDragged( MouseEvent e ) {
			super.mouseDragged( e );
			mouseX = e.getX();
			mouseY = e.getY();
		}

		@Override
		public void mouseMoved( MouseEvent e ) {
			super.mouseMoved( e );
			mouseX = e.getX();
			mouseY = e.getY();
		}

		@Override
		public void mousePressed( MouseEvent e ) {
			super.mousePressed( e );
			buttonPressed.add( Button.getButton( e.getButton() ) );
		}

		@Override
		public void mouseReleased( MouseEvent e ) {
			super.mouseReleased( e );
			buttonPressed.remove( Button.getButton( e.getButton() ) );
			buttonTyped.add( Button.getButton( e.getButton() ) );
		}
		
	}
	
	private class InputReceiver extends KeyAdapter {

		@Override
		public void keyPressed( KeyEvent e ) {
			super.keyPressed( e );
			keyPressed.add( Key.getKey( e.getKeyCode() ) );
			
			char c = e.getKeyChar();
			if( Character.isDefined( c ) )
				charPressed.add( e.getKeyChar() );
		}

		@Override
		public void keyReleased( KeyEvent e ) {
			super.keyReleased( e );
			keyPressed.remove( Key.getKey( e.getKeyCode() ) );
			keyTyped.add( Key.getKey( e.getKeyCode() ) );
		}

	}
	/**
	 * 
	 */
	public static enum Key {
		/**
		 * 
		 */
		Key_A( KeyEvent.VK_A ),
		/**
		 * 
		 */
		Key_B( KeyEvent.VK_B ),
		/**
		 * 
		 */
		Key_C( KeyEvent.VK_C ),
		/**
		 * 
		 */
		Key_D( KeyEvent.VK_D ),
		/**
		 * 
		 */
		Key_E( KeyEvent.VK_E ),
		/**
		 * 
		 */
		Key_F( KeyEvent.VK_F ),
		/**
		 * 
		 */
		Key_G( KeyEvent.VK_G ),
		/**
		 * 
		 */
		Key_H( KeyEvent.VK_H ),
		/**
		 * 
		 */
		Key_I( KeyEvent.VK_I ),
		/**
		 * 
		 */
		Key_J( KeyEvent.VK_J ),
		/**
		 * 
		 */
		Key_K( KeyEvent.VK_K ),
		/**
		 * 
		 */
		Key_L( KeyEvent.VK_L ),
		/**
		 * 
		 */
		Key_M( KeyEvent.VK_M ),
		/**
		 * 
		 */
		Key_N( KeyEvent.VK_N ),
		/**
		 * 
		 */
		Key_O( KeyEvent.VK_O ),
		/**
		 * 
		 */
		Key_P( KeyEvent.VK_P ),
		/**
		 * 
		 */
		Key_Q( KeyEvent.VK_Q ),
		/**
		 * 
		 */
		Key_R( KeyEvent.VK_R ),
		/**
		 * 
		 */
		Key_S( KeyEvent.VK_S ),
		/**
		 * 
		 */
		Key_T( KeyEvent.VK_T ),
		/**
		 * 
		 */
		Key_U( KeyEvent.VK_U ),
		/**
		 * 
		 */
		Key_V( KeyEvent.VK_V ),
		/**
		 * 
		 */
		Key_W( KeyEvent.VK_W ),
		/**
		 * 
		 */
		Key_X( KeyEvent.VK_X ),
		/**
		 * 
		 */
		Key_Y( KeyEvent.VK_Y ),
		/**
		 * 
		 */
		Key_Z( KeyEvent.VK_Z ),

		/**
		 * 
		 */
		Key_0( KeyEvent.VK_0 ),
		/**
		 * 
		 */
		Key_1( KeyEvent.VK_1 ),
		/**
		 * 
		 */
		Key_2( KeyEvent.VK_2 ),
		/**
		 * 
		 */
		Key_3( KeyEvent.VK_3 ),
		/**
		 * 
		 */
		Key_4( KeyEvent.VK_4 ),
		/**
		 * 
		 */
		Key_5( KeyEvent.VK_5 ),
		/**
		 * 
		 */
		Key_6( KeyEvent.VK_6 ),
		/**
		 * 
		 */
		Key_7( KeyEvent.VK_7 ),
		/**
		 * 
		 */
		Key_8( KeyEvent.VK_8 ),
		/**
		 * 
		 */
		Key_9( KeyEvent.VK_9 ),
		
		/**
		 * 
		 */
		Key_F1( KeyEvent.VK_F1 ),
		/**
		 * 
		 */
		Key_F2( KeyEvent.VK_F2 ),
		/**
		 * 
		 */
		Key_F3( KeyEvent.VK_F3 ),
		/**
		 * 
		 */
		Key_F4( KeyEvent.VK_F4 ),
		/**
		 * 
		 */
		Key_F5( KeyEvent.VK_F5 ),
		/**
		 * 
		 */
		Key_F6( KeyEvent.VK_F6 ),
		/**
		 * 
		 */
		Key_F7( KeyEvent.VK_F7 ),
		/**
		 * 
		 */
		Key_F8( KeyEvent.VK_F8 ),
		/**
		 * 
		 */
		Key_F9( KeyEvent.VK_F9 ),
		/**
		 * 
		 */
		Key_F10( KeyEvent.VK_F10 ),
		/**
		 * 
		 */
		Key_F11( KeyEvent.VK_F11 ),
		/**
		 * 
		 */
		Key_F12( KeyEvent.VK_F12 ),
	
		/**
		 * 
		 */
		Key_Enter( KeyEvent.VK_ENTER ),
		/**
		 * 
		 */
		Key_Shift( KeyEvent.VK_SHIFT ),
		/**
		 * 
		 */
		Key_Strg( KeyEvent.VK_CONTROL ),
		/**
		 * 
		 */
		Key_Alt( KeyEvent.VK_ALT ),
		/**
		 * 
		 */
		Key_Space( KeyEvent.VK_SPACE ),
		
		/**
		 * 
		 */
		Key_Left( KeyEvent.VK_LEFT ),
		/**
		 * 
		 */
		Key_Right( KeyEvent.VK_RIGHT ),
		/**
		 * 
		 */
		Key_Up( KeyEvent.VK_UP ),
		/**
		 * 
		 */
		Key_Down( KeyEvent.VK_DOWN ),
		
		/**
		 * 
		 */
		Key_Undefined( -1 );
		
		private final int awtKey;

		private Key( int awtKey ) {
			this.awtKey = awtKey;
		}
		
		/**
		 * 
		 * @param awtKey
		 * @return
		 */
		public static Key getKey( int awtKey ) {
			for( Key k : Key.values() )
				if( k.awtKey == awtKey )
					return k;
			return Key_Undefined;
		}
		
	}
	
	/**
	 * 
	 */
	public static enum Button {
		/**
		 * 
		 */
		Mouse_1( MouseEvent.BUTTON1 ),
		/**
		 * 
		 */
		Mouse_2( MouseEvent.BUTTON2 ),
		/**
		 * 
		 */
		Mouse_3( MouseEvent.BUTTON3 ),
		/**
		 * 
		 */
		Mouse_Undefined( -1 );
		
		private final int awtButton;

		private Button( int awtButton ) {
			this.awtButton = awtButton;
		}
		
		/**
		 * 
		 * @param awtButton
		 * @return
		 */
		public static Button getButton( int awtButton ) {
			for( Button k : Button.values() )
				if( k.awtButton == awtButton )
					return k;
			return Mouse_Undefined;
		}
		
	}
	
}
